﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace PlyViewer
{
    public static class PlyReader
    {
        public static PlyPointCloud ReadPlyFile(string filePath)
        {
            var pointCloud = new PlyPointCloud();
            pointCloud.FileName = Path.GetFileName(filePath);

            try
            {
                using (var reader = new StreamReader(filePath))
                {
                    string line;
                    bool readingHeader = true;
                    int vertexCount = 0;
                    int currentVertex = 0;
                    bool hasColor = false;
                    List<string> propertyOrder = new List<string>();

                    // 读取文件头
                    while (readingHeader && (line = reader.ReadLine()) != null)
                    {
                        line = line.Trim();

                        if (line.StartsWith("element vertex"))
                        {
                            var parts = line.Split(' ');
                            vertexCount = int.Parse(parts[2]);
                        }
                        else if (line.StartsWith("property"))
                        {
                            var parts = line.Split(' ');
                            if (parts.Length >= 3)
                            {
                                propertyOrder.Add(parts[2]);
                                if (parts[2] == "red" || parts[2] == "green" || parts[2] == "blue" ||
                                    parts[2] == "r" || parts[2] == "g" || parts[2] == "b")
                                {
                                    hasColor = true;
                                }
                            }
                        }
                        else if (line == "end_header")
                        {
                            readingHeader = false;
                        }
                    }

                    // 读取顶点数据
                    while (currentVertex < vertexCount && (line = reader.ReadLine()) != null)
                    {
                        line = line.Trim();
                        if (string.IsNullOrEmpty(line)) continue;

                        var parts = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);

                        if (parts.Length >= 3)
                        {
                            // 读取坐标
                            double x = ParseDouble(parts[0]);
                            double y = ParseDouble(parts[1]);
                            double z = ParseDouble(parts[2]);

                            pointCloud.Points.Add(new Point3D(x, y, z));

                            // 读取颜色
                            if (hasColor && parts.Length >= 6)
                            {
                                byte r = ParseByte(parts[3]);
                                byte g = ParseByte(parts[4]);
                                byte b = ParseByte(parts[5]);
                                pointCloud.Colors.Add(Color.FromRgb(r, g, b));
                            }
                            else
                            {
                                pointCloud.Colors.Add(Colors.White);
                            }
                        }

                        currentVertex++;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"读取PLY文件时出错: {ex.Message}", ex);
            }

            return pointCloud;
        }

        private static double ParseDouble(string value)
        {
            return double.Parse(value, CultureInfo.InvariantCulture);
        }

        private static byte ParseByte(string value)
        {
            if (value.Contains("."))
            {
                double floatValue = double.Parse(value, CultureInfo.InvariantCulture);
                return (byte)(floatValue * 255);
            }
            else
            {
                return byte.Parse(value);
            }
        }
    }
}